// Code generated by smithy-go-codegen DO NOT EDIT.

package s3

import (
	
	
	
	awsmiddleware 
	
	s3cust 
	
	
	smithytime 
	smithyhttp 
	smithywaiter 
	
)

// This action is useful to determine if a bucket exists and you have permission to
// access it. The action returns a 200 OK if the bucket exists and you have
// permission to access it. If the bucket does not exist or you do not have
// permission to access it, the HEAD request returns a generic 404 Not Found or 403
// Forbidden code. A message body is not included, so you cannot determine the
// exception beyond these error codes. To use this operation, you must have
// permissions to perform the s3:ListBucket action. The bucket owner has this
// permission by default and can grant this permission to others. For more
// information about permissions, see Permissions Related to Bucket Subresource
// Operations
// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
// and Managing Access Permissions to Your Amazon S3 Resources
// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).
// To use this API against an access point, you must provide the alias of the
// access point in place of the bucket name or specify the access point ARN. When
// using the access point ARN, you must direct requests to the access point
// hostname. The access point hostname takes the form
// AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using the
// Amazon Web Services SDKs, you provide the ARN in place of the bucket name. For
// more information see, Using access points
// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html).
func ( *Client) ( context.Context,  *HeadBucketInput,  ...func(*Options)) (*HeadBucketOutput, error) {
	if  == nil {
		 = &HeadBucketInput{}
	}

	, ,  := .invokeOperation(, "HeadBucket", , , .addOperationHeadBucketMiddlewares)
	if  != nil {
		return nil, 
	}

	 := .(*HeadBucketOutput)
	.ResultMetadata = 
	return , nil
}

type HeadBucketInput struct {

	// The bucket name. When using this action with an access point, you must direct
	// requests to the access point hostname. The access point hostname takes the form
	// AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this
	// action with an access point through the Amazon Web Services SDKs, you provide
	// the access point ARN in place of the bucket name. For more information about
	// access point ARNs, see Using access points
	// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html)
	// in the Amazon S3 User Guide. When using this action with Amazon S3 on Outposts,
	// you must direct requests to the S3 on Outposts hostname. The S3 on Outposts
	// hostname takes the form
	// AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using
	// this action with S3 on Outposts through the Amazon Web Services SDKs, you
	// provide the Outposts bucket ARN in place of the bucket name. For more
	// information about S3 on Outposts ARNs, see Using Amazon S3 on Outposts
	// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3onOutposts.html) in the
	// Amazon S3 User Guide.
	//
	// This member is required.
	Bucket *string

	// The account ID of the expected bucket owner. If the bucket is owned by a
	// different account, the request fails with the HTTP status code 403 Forbidden
	// (access denied).
	ExpectedBucketOwner *string

	noSmithyDocumentSerde
}

type HeadBucketOutput struct {
	// Metadata pertaining to the operation's result.
	ResultMetadata middleware.Metadata

	noSmithyDocumentSerde
}

func ( *Client) ( *middleware.Stack,  Options) ( error) {
	 = .Serialize.Add(&awsRestxml_serializeOpHeadBucket{}, middleware.After)
	if  != nil {
		return 
	}
	 = .Deserialize.Add(&awsRestxml_deserializeOpHeadBucket{}, middleware.After)
	if  != nil {
		return 
	}
	if  = addSetLoggerMiddleware(, );  != nil {
		return 
	}
	if  = awsmiddleware.AddClientRequestIDMiddleware();  != nil {
		return 
	}
	if  = smithyhttp.AddComputeContentLengthMiddleware();  != nil {
		return 
	}
	if  = addResolveEndpointMiddleware(, );  != nil {
		return 
	}
	if  = v4.AddComputePayloadSHA256Middleware();  != nil {
		return 
	}
	if  = addRetryMiddlewares(, );  != nil {
		return 
	}
	if  = addHTTPSignerV4Middleware(, );  != nil {
		return 
	}
	if  = awsmiddleware.AddRawResponseToMetadata();  != nil {
		return 
	}
	if  = awsmiddleware.AddRecordResponseTiming();  != nil {
		return 
	}
	if  = addClientUserAgent();  != nil {
		return 
	}
	if  = smithyhttp.AddErrorCloseResponseBodyMiddleware();  != nil {
		return 
	}
	if  = smithyhttp.AddCloseResponseBodyMiddleware();  != nil {
		return 
	}
	if  = swapWithCustomHTTPSignerMiddleware(, );  != nil {
		return 
	}
	if  = addOpHeadBucketValidationMiddleware();  != nil {
		return 
	}
	if  = .Initialize.Add(newServiceMetadataMiddleware_opHeadBucket(.Region), middleware.Before);  != nil {
		return 
	}
	if  = addMetadataRetrieverMiddleware();  != nil {
		return 
	}
	if  = addHeadBucketUpdateEndpoint(, );  != nil {
		return 
	}
	if  = addResponseErrorMiddleware();  != nil {
		return 
	}
	if  = v4.AddContentSHA256HeaderMiddleware();  != nil {
		return 
	}
	if  = disableAcceptEncodingGzip();  != nil {
		return 
	}
	if  = addRequestResponseLogging(, );  != nil {
		return 
	}
	return nil
}

// HeadBucketAPIClient is a client that implements the HeadBucket operation.
type HeadBucketAPIClient interface {
	HeadBucket(context.Context, *HeadBucketInput, ...func(*Options)) (*HeadBucketOutput, error)
}

var _ HeadBucketAPIClient = (*Client)(nil)

// BucketExistsWaiterOptions are waiter options for BucketExistsWaiter
type BucketExistsWaiterOptions struct {

	// Set of options to modify how an operation is invoked. These apply to all
	// operations invoked for this client. Use functional options on operation call to
	// modify this list for per operation behavior.
	APIOptions []func(*middleware.Stack) error

	// MinDelay is the minimum amount of time to delay between retries. If unset,
	// BucketExistsWaiter will use default minimum delay of 5 seconds. Note that
	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
	MinDelay time.Duration

	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
	// to zero, BucketExistsWaiter will use default max delay of 120 seconds. Note that
	// MaxDelay must resolve to value greater than or equal to the MinDelay.
	MaxDelay time.Duration

	// LogWaitAttempts is used to enable logging for waiter retry attempts
	LogWaitAttempts bool

	// Retryable is function that can be used to override the service defined
	// waiter-behavior based on operation output, or returned error. This function is
	// used by the waiter to decide if a state is retryable or a terminal state. By
	// default service-modeled logic will populate this option. This option can thus be
	// used to define a custom waiter state with fall-back to service-modeled waiter
	// state mutators.The function returns an error in case of a failure state. In case
	// of retry state, this function returns a bool value of true and nil error, while
	// in case of success it returns a bool value of false and nil error.
	Retryable func(context.Context, *HeadBucketInput, *HeadBucketOutput, error) (bool, error)
}

// BucketExistsWaiter defines the waiters for BucketExists
type BucketExistsWaiter struct {
	client HeadBucketAPIClient

	options BucketExistsWaiterOptions
}

// NewBucketExistsWaiter constructs a BucketExistsWaiter.
func ( HeadBucketAPIClient,  ...func(*BucketExistsWaiterOptions)) *BucketExistsWaiter {
	 := BucketExistsWaiterOptions{}
	.MinDelay = 5 * time.Second
	.MaxDelay = 120 * time.Second
	.Retryable = bucketExistsStateRetryable

	for ,  := range  {
		(&)
	}
	return &BucketExistsWaiter{
		client:  ,
		options: ,
	}
}

// Wait calls the waiter function for BucketExists waiter. The maxWaitDur is the
// maximum wait duration the waiter will wait. The maxWaitDur is required and must
// be greater than zero.
func ( *BucketExistsWaiter) ( context.Context,  *HeadBucketInput,  time.Duration,  ...func(*BucketExistsWaiterOptions)) error {
	,  := .WaitForOutput(, , , ...)
	return 
}

// WaitForOutput calls the waiter function for BucketExists waiter and returns the
// output of the successful operation. The maxWaitDur is the maximum wait duration
// the waiter will wait. The maxWaitDur is required and must be greater than zero.
func ( *BucketExistsWaiter) ( context.Context,  *HeadBucketInput,  time.Duration,  ...func(*BucketExistsWaiterOptions)) (*HeadBucketOutput, error) {
	if  <= 0 {
		return nil, fmt.Errorf("maximum wait time for waiter must be greater than zero")
	}

	 := .options
	for ,  := range  {
		(&)
	}

	if .MaxDelay <= 0 {
		.MaxDelay = 120 * time.Second
	}

	if .MinDelay > .MaxDelay {
		return nil, fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", .MinDelay, .MaxDelay)
	}

	,  := context.WithTimeout(, )
	defer ()

	 := smithywaiter.Logger{}
	 := 

	var  int64
	for {

		++
		 := .APIOptions
		 := time.Now()

		if .LogWaitAttempts {
			.Attempt = 
			 = append([]func(*middleware.Stack) error{}, .APIOptions...)
			 = append(, .AddLogger)
		}

		,  := .client.HeadBucket(, , func( *Options) {
			.APIOptions = append(.APIOptions, ...)
		})

		,  := .Retryable(, , , )
		if  != nil {
			return nil, 
		}
		if ! {
			return , nil
		}

		 -= time.Since()
		if  < .MinDelay ||  <= 0 {
			break
		}

		// compute exponential backoff between waiter retries
		,  := smithywaiter.ComputeDelay(
			, .MinDelay, .MaxDelay, ,
		)
		if  != nil {
			return nil, fmt.Errorf("error computing waiter delay, %w", )
		}

		 -= 
		// sleep for the delay amount before invoking a request
		if  := smithytime.SleepWithContext(, );  != nil {
			return nil, fmt.Errorf("request cancelled while waiting, %w", )
		}
	}
	return nil, fmt.Errorf("exceeded max wait time for BucketExists waiter")
}

func ( context.Context,  *HeadBucketInput,  *HeadBucketOutput,  error) (bool, error) {

	if  == nil {
		return false, nil
	}

	if  != nil {
		var  *types.NotFound
		if errors.As(, &) {
			return true, nil
		}
	}

	return true, nil
}

// BucketNotExistsWaiterOptions are waiter options for BucketNotExistsWaiter
type BucketNotExistsWaiterOptions struct {

	// Set of options to modify how an operation is invoked. These apply to all
	// operations invoked for this client. Use functional options on operation call to
	// modify this list for per operation behavior.
	APIOptions []func(*middleware.Stack) error

	// MinDelay is the minimum amount of time to delay between retries. If unset,
	// BucketNotExistsWaiter will use default minimum delay of 5 seconds. Note that
	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
	MinDelay time.Duration

	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
	// to zero, BucketNotExistsWaiter will use default max delay of 120 seconds. Note
	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
	MaxDelay time.Duration

	// LogWaitAttempts is used to enable logging for waiter retry attempts
	LogWaitAttempts bool

	// Retryable is function that can be used to override the service defined
	// waiter-behavior based on operation output, or returned error. This function is
	// used by the waiter to decide if a state is retryable or a terminal state. By
	// default service-modeled logic will populate this option. This option can thus be
	// used to define a custom waiter state with fall-back to service-modeled waiter
	// state mutators.The function returns an error in case of a failure state. In case
	// of retry state, this function returns a bool value of true and nil error, while
	// in case of success it returns a bool value of false and nil error.
	Retryable func(context.Context, *HeadBucketInput, *HeadBucketOutput, error) (bool, error)
}

// BucketNotExistsWaiter defines the waiters for BucketNotExists
type BucketNotExistsWaiter struct {
	client HeadBucketAPIClient

	options BucketNotExistsWaiterOptions
}

// NewBucketNotExistsWaiter constructs a BucketNotExistsWaiter.
func ( HeadBucketAPIClient,  ...func(*BucketNotExistsWaiterOptions)) *BucketNotExistsWaiter {
	 := BucketNotExistsWaiterOptions{}
	.MinDelay = 5 * time.Second
	.MaxDelay = 120 * time.Second
	.Retryable = bucketNotExistsStateRetryable

	for ,  := range  {
		(&)
	}
	return &BucketNotExistsWaiter{
		client:  ,
		options: ,
	}
}

// Wait calls the waiter function for BucketNotExists waiter. The maxWaitDur is the
// maximum wait duration the waiter will wait. The maxWaitDur is required and must
// be greater than zero.
func ( *BucketNotExistsWaiter) ( context.Context,  *HeadBucketInput,  time.Duration,  ...func(*BucketNotExistsWaiterOptions)) error {
	,  := .WaitForOutput(, , , ...)
	return 
}

// WaitForOutput calls the waiter function for BucketNotExists waiter and returns
// the output of the successful operation. The maxWaitDur is the maximum wait
// duration the waiter will wait. The maxWaitDur is required and must be greater
// than zero.
func ( *BucketNotExistsWaiter) ( context.Context,  *HeadBucketInput,  time.Duration,  ...func(*BucketNotExistsWaiterOptions)) (*HeadBucketOutput, error) {
	if  <= 0 {
		return nil, fmt.Errorf("maximum wait time for waiter must be greater than zero")
	}

	 := .options
	for ,  := range  {
		(&)
	}

	if .MaxDelay <= 0 {
		.MaxDelay = 120 * time.Second
	}

	if .MinDelay > .MaxDelay {
		return nil, fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", .MinDelay, .MaxDelay)
	}

	,  := context.WithTimeout(, )
	defer ()

	 := smithywaiter.Logger{}
	 := 

	var  int64
	for {

		++
		 := .APIOptions
		 := time.Now()

		if .LogWaitAttempts {
			.Attempt = 
			 = append([]func(*middleware.Stack) error{}, .APIOptions...)
			 = append(, .AddLogger)
		}

		,  := .client.HeadBucket(, , func( *Options) {
			.APIOptions = append(.APIOptions, ...)
		})

		,  := .Retryable(, , , )
		if  != nil {
			return nil, 
		}
		if ! {
			return , nil
		}

		 -= time.Since()
		if  < .MinDelay ||  <= 0 {
			break
		}

		// compute exponential backoff between waiter retries
		,  := smithywaiter.ComputeDelay(
			, .MinDelay, .MaxDelay, ,
		)
		if  != nil {
			return nil, fmt.Errorf("error computing waiter delay, %w", )
		}

		 -= 
		// sleep for the delay amount before invoking a request
		if  := smithytime.SleepWithContext(, );  != nil {
			return nil, fmt.Errorf("request cancelled while waiting, %w", )
		}
	}
	return nil, fmt.Errorf("exceeded max wait time for BucketNotExists waiter")
}

func ( context.Context,  *HeadBucketInput,  *HeadBucketOutput,  error) (bool, error) {

	if  != nil {
		var  *types.NotFound
		if errors.As(, &) {
			return false, nil
		}
	}

	return true, nil
}

func ( string) *awsmiddleware.RegisterServiceMetadata {
	return &awsmiddleware.RegisterServiceMetadata{
		Region:        ,
		ServiceID:     ServiceID,
		SigningName:   "s3",
		OperationName: "HeadBucket",
	}
}

// getHeadBucketBucketMember returns a pointer to string denoting a provided bucket
// member valueand a boolean indicating if the input has a modeled bucket name,
func ( interface{}) (*string, bool) {
	 := .(*HeadBucketInput)
	if .Bucket == nil {
		return nil, false
	}
	return .Bucket, true
}
func ( *middleware.Stack,  Options) error {
	return s3cust.UpdateEndpoint(, s3cust.UpdateEndpointOptions{
		Accessor: s3cust.UpdateEndpointParameterAccessor{
			GetBucketFromInput: getHeadBucketBucketMember,
		},
		UsePathStyle:                   .UsePathStyle,
		UseAccelerate:                  .UseAccelerate,
		SupportsAccelerate:             true,
		TargetS3ObjectLambda:           false,
		EndpointResolver:               .EndpointResolver,
		EndpointResolverOptions:        .EndpointOptions,
		UseARNRegion:                   .UseARNRegion,
		DisableMultiRegionAccessPoints: .DisableMultiRegionAccessPoints,
	})
}

// PresignHeadBucket is used to generate a presigned HTTP Request which contains
// presigned URL, signed headers and HTTP method used.
func ( *PresignClient) ( context.Context,  *HeadBucketInput,  ...func(*PresignOptions)) (*v4.PresignedHTTPRequest, error) {
	if  == nil {
		 = &HeadBucketInput{}
	}
	 := .options.copy()
	for ,  := range  {
		(&)
	}
	 := append(.ClientOptions, withNopHTTPClientAPIOption)

	, ,  := .client.invokeOperation(, "HeadBucket", , ,
		.client.addOperationHeadBucketMiddlewares,
		presignConverter().convertToPresignMiddleware,
		addHeadBucketPayloadAsUnsigned,
	)
	if  != nil {
		return nil, 
	}

	 := .(*v4.PresignedHTTPRequest)
	return , nil
}

func ( *middleware.Stack,  Options) error {
	v4.RemoveContentSHA256HeaderMiddleware()
	v4.RemoveComputePayloadSHA256Middleware()
	return v4.AddUnsignedPayloadMiddleware()
}